/**
 * Class allowing translation of elements in page
 * Works with JQuery Mobile widgets
 *
 * @author Naxan
 */
var WebappI18n = new (function() {
	
	var $this = this;
	var dictionary;
	var defaultLang;
	
	
	/**
	 * Get params i18n of an element
	 */
	function getParamsI18nElement(e) {
		var attributes = $(e)[0].attributes;
		var params = {};
		for (var i = 0; i < attributes.length; i++) {
			var attr = attributes[i];
			if (attr.nodeName.substr(0, 11) == "i18n-param-") {
				var name = attr.nodeName.substr(11);
				var value = attr.nodeValue;
			}
			params[name] = value;
		}
		return params;
	}
	
	/**
	 * Format a text with params
	 */
	function format(str, params) {
		return str.replace(/{([0-9A-Za-z_-]*)}/g, function(match, name) { 
			var value = match;
			if (typeof(params[name]) != "undefined") {
				value = params[name];
			}
			return value;
		});
	}
	
	/**
	 * Init the i18n on an element and his childs
	 * Change the text of alls elements who have the css class Webapp18n.className (default to 'i18n')
	 */
	this.init = function(dom, jqmPageID) {
		var elems = $(dom).find(WebappI18n.className);
		for (var i = 0; i < elems.length; i++) {
			var e = $(elems[i]);
			var name = getElemI18nID(e);
			
			if (name.length == 0) {
				continue;
			}
			
			var params = getParamsI18nElement(e);
			var options = {};
			var translation;
			
			// If jquery-mobile, tests with and without the pageid in subitem
			if (jqmPageID) {
				translation = $this.getItem(name, {subItem: jqmPageID});
				if (!translation) {
					translation = $this.getItem(name);
				}
				
			}
			else {
				translation = $this.getItem(name);
			}
			
			// Only if there is a translation founded
			if (translation) {
				
				switch (e.prop("tagName").toLowerCase()) {
					case 'input':
					case 'textarea':
						// input and textarea: .val
						translation = format(translation, params);
						switch(e.attr('type')) {
							case 'search':
							case 'text':
								e.attr('placeholder', translation);
								break;
							case 'button':
								if ($this.isJQM() && e.hasClass('ui-btn-hidden')) {
									e.button('refresh');
								}
							default: 
								e.val(translation);
						}
						break;
					case 'select':
						// Case select: object {value1: 'text1', value2: 'text2}
						if (typeof(translation) == "object") {
							for (var j in translation) {
								var option = 'option[value="'+j+'"]';
								var text = format(translation[j], params);
								e.find(option).html(translation[j]);
							}
						}
						if ($this.isJQM()) {
							e.selectmenu("refresh");
						}
						break;
					
					default:
						// other elements: .html()
						translation = format(translation, params);
						if ($this.isJQM() && (e.hasClass("ui-btn") || e.hasClass("ui-collapsible-heading"))) {
							e.find(".ui-btn-inner .ui-btn-text").html(translation);
						}
						else {
							e.html(translation);
						}
						break;
				}
			}
			else { // if not, display an error
				if ($this.isJQM() && jqmPageID) {
					name += " (#"+jqmPageID+")";
				}
				alert("Translation not found for '"+name+"'");
			}
			
		}
	}
	
	/**
	 * Set the dictionary
	 * If lang is omitted, the object passed have to have this struct:
		{
			en: {
				item1: 'text',
				item2: 'text 2';
				groupitem: {
					item1: 'text'
				}
			},
			fr: {
				...
			}
		*
	 *
	 */
	this.setDictionary = function(o, lang) {
		if (!lang) {
			dictionary = o;
		}
		else {
			if (!dictionary) {
				dictionary = {};
			}
			dictionary[lang] = o;
		}
	}
	
	/**
	 * Change the default lang searched in dictionary
	 */
	this.setDefaultLang = function(lang) {
		defaultLang = lang;
	}
	
	/**
	 * Get the default lang searched in dictionary
	 */
	this.getDefaultLang = function() {
		return defaultLang;
	}
	
	/**
	 * Search the ID I18n of an element
	 * Either the attribute i18n-id, either the id of the element and the id of all the parents
	 * JQueryMobile: The id of the parents stopped at the page (the page id is not taken)
	 */
	function getElemI18nID(e, searchParent) {
		var id = "";
		var ids;
		if ($(e).attr("i18n-id")) {
			id = $(e).attr("i18n-id");
		}
		else {
			id = $(e).attr("id");
			ids = [];
			if (id) {
				ids.push(id);
			}
			if (id || searchParent) {
				var parent = $(e).parent();
				if (parent.length > 0 && !($this.isJQM() && parent.hasClass("ui-page"))) {
					var idparent = getElemI18nID(parent, true);
					if (idparent) {
						var idsparent = idparent.split(".");
						var idtemp;
						while (idtemp = idsparent.pop()) {
							ids.unshift(idtemp);
						}
					}
				}
			}
			id = ids.join(".");
		}
		return id;
	}
	
	/**
	 * Send an error
	 */
	function error(e) {
		if (typeof(console) != "undefined" && typeof(console.error) != "undefined") {
			console.error(e);
		}
	}
	
	/**
	 * Get an item from dictionary
	 * Options:
	 * - strict: search the exact item with the exact parents
	 * - subItem: search the item in the subItem
	 * - lang: lang (default to defaultLang)
	 */
	this.getItem = function(name, options) {
		if (!options) {
			options = {};
		}
		var lang = options.lang;
		if (!lang) {
			lang = defaultLang;
		}

		// Error checks
		if (!lang) {
			error("No lang selected");
		}
		else if (typeof(dictionary) == "undefined") {
			error("No dictionary set");
		}
		else if (typeof(dictionary[lang]) == "undefined") {
			error("Lang '"+lang+"' doesn't exist in dictionary");
		}
		else {
			var names = name.split(".");
			var value = null;
			while (names.length > 0) {
				var o = dictionary[lang];
				
				// Option subItem
				if (options.subItem) {
					var options2 = options;
					o = $this.getItem(options.subItem);
					if (!o || typeof(o) != "object") {
						error("Subitem "+options.subItem+" not found in Dictionary");
						return;
					}
				}
				founded = true;
				
				// Searching term and removing parents oldest first
				for (var i = 0; i < names.length; i++) {
					var n = names[i];
					var nTiret = tiretToMAJ(n);
					if (typeof(o[n]) != "undefined") {
						o = o[n];
					}
					else if (typeof(o[nTiret]) != "undefined") {
						o = o[nTiret];
					}
					else {
						founded = false;
						break;
					}
				}
				
				// Option strict: 1 iteration only
				if (!founded && !options.strict) {
					names.shift();
				}
				else {
					if (founded) {
						value = o;
					}
					break;
				}
			}
			return value;
		}
	}
	
	/**
	 * Transform a string of "test1-test2" in "test1Test2"
	 */
	function tiretToMAJ(t) {
		var texts = t.split("-");
		for (var i = 1; i < texts.length; i++) {
			var c = texts[i].charAt(0).toUpperCase();
			texts[i] = c+texts[i].substr(1);
		}
		var newt = texts.join("");
		return newt;
	}
	
	/**
	 * Test if there are JQueryMobile
	 */
	this.isJQM = function() {
		return (typeof($) != "undefined" && typeof($.mobile) != "undefined");
	}
	
	/**
	 * Init a page of JQueryMobile
	 */
	function initPageJQM() {
		var page = $(this);
		$this.init(page, page.attr("id"));
	}
	
	/**
	 * Refresh the current page
	 */
	this.refreshPage = function() {
		if ($this.isJQM()) {
			var currentPage = $(".ui-page-active");
			$this.init(currentPage, currentPage.attr("id")); 
		}
		else {
			$this.init(document);
		}
	}
	
	/**
	 * Initialization at ready of document
	 */
	$(document).ready(function() {
		if (WebappI18n.autoInit) {
			if ($this.isJQM()) {
				$("body").on("pageinit", ".ui-page", initPageJQM);
				$("body").on("pagebeforeshow", ".ui-page", initPageJQM);
				var currentPage = $(".ui-page-active");
				if (currentPage.length) {
					$this.init(currentPage, currentPage.attr("id")); 				
				}
			}
			else { 
				$this.init(document);
			}
		}
	});
});

/**
 * The CSS Class for elements who must be translated
 */
WebappI18n.className = ".i18n";

/**
 * Auto-init at ready page
 */
WebappI18n.autoInit = true;

